#!/usr/bin/env python
# -*- coding:utf-8 -*-
import json
from urllib.parse import urlencode, parse_qs
# import urllib
from urllib.request import urlopen

import logging

# from django.conf import settings
from meiduo_mall.settings import dev
from oauth import constants
from oauth.exceptions import OAuthQQAPIError
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer, BadData


def get_qq_conf_value(instance, attr_name, error_msg):
    assert hasattr(instance, attr_name), error_msg
    return instance.attr_name


logger = logging.getLogger('django')


class OAuthQQ():
    """
    QQ认证的辅助工具类
    """

    def __init__(self, client_id=None, client_secret=None, redirect_uri=None, state=None):
        self.client_id = client_id or dev.QQ_CLIENT_ID
        self.client_secret = client_secret or dev.QQ_CLIENT_SECRET
        self.redirect_uri = redirect_uri or dev.QQ_REDIRECT_URI
        self.state = state or dev.QQ_STATE

        # if client_id is None:
        #     assert hasattr(settings,'QQ_CLIENT_ID'),'请在配置文件做配置QQ_CLIENT_ID的值'
        #     self.client_id = client_id
        # TODO 有问题 待解决
        # self.client_id = get_qq_conf_value(dev,'QQ_CLIENT_ID','请在配置文件做配置QQ_CLIENT_ID的值')
        # self.client_secret = get_qq_conf_value(dev,'QQ_CLIENT_SECRET','请在配置文件做配置QQ_CLIENT_SECRET的值')
        # self.redirect_uri = get_qq_conf_value(dev,'QQ_REDIRECT_URI','请在配置文件做配置QQ_REDIRECT_URI的值')
        # self.state = get_qq_conf_value(dev,'QQ_STATE','请在配置文件做配置QQ_STATE的值')

    def get_qq_login_url(self):
        '''获取QQ登录网址'''
        params = {
            'response_type': 'code',
            'client_id': self.client_id,
            'redirect_uri': self.redirect_uri,
            'state': self.state,
            # 'scope': 'get_user_info',
        }
        url = 'https://graph.qq.com/oauth2.0/authorize?' + urlencode(params)
        return url

    def get_access_token(self, code):
        """
        获取access__token
        :param code: qq提供的code
        :return: access__token
        """
        params = {
            'grant_type': 'authorization_code',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'code': code,
            'redirect_uri': self.redirect_uri
        }
        url = 'https://graph.qq.com/oauth2.0/token?' + urlencode(params)
        try:
            response = urlopen(url)
            response_data = response.read().decode()
            # 转成字典,值是列表
            data = parse_qs(response_data)
        except Exception as e:
            logger.error('获取access_token异常：%s' % e)
            raise OAuthQQAPIError
        else:

            access_token = data.get('access_token', None)
            if not access_token:
                logger.error("code=%s msg=%s" % (data.get('code'), data.get('msg')))
                raise OAuthQQAPIError
            return access_token[0]

    def get_openid(self, access_token):
        '''获取用户的openid'''
        url = 'https://graph.qq.com/oauth2.0/me?access_token=' + access_token
        try:
            # 发送请求
            resp = urlopen(url)
            # 读取响应体数据
            resp_data = resp.read().decode()
            # 返回的数据 callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )\n;
            resp_data = resp_data[10:-4]
            # 转成查询字符串
            resp_data = json.loads(resp_data)
            print("resp_data:", resp_data)
        except Exception as e:
            logger.error('获取openid异常：%s' % e)
            raise OAuthQQAPIError
        else:
            openid = resp_data.get('openid', None)
            print("openid:", openid)
            return openid

    def generate_bind_user_access_token(self, openid):
        serializer = TJWSSerializer(dev.SECRET_KEY, constants.BIND_USER_ACCESS_TOKEN_EXPIRES)
        # serializer.dumps(数据), 返回bytes类型
        access_token = serializer.dumps({'openid': openid})
        print("JWT dangrous dumps:", access_token)
        return access_token.decode()

    @staticmethod
    def check_bind_user_access_token(access_token):
        serializer = TJWSSerializer(dev.SECRET_KEY, constants.BIND_USER_ACCESS_TOKEN_EXPIRES)
        try:
            # 检验token
            # 验证失败，会抛出itsdangerous.BadData异常
            data = serializer.loads(access_token)
            print('JWT dangrous loads:', data)
        except BadData:
            return None
        else:
            return data['openid']
